iT邦幫忙

2026 iThome 鐵人賽

DAY 0
0
AI 自動化

你的 Agent 流程不該是一篇散文系列 第 2

Day2 它是怎麼長胖的:一次事故一條規則

  • 分享至 

  • xImage
  •  

昨天寫到,這條用 skill 編排的 AI 開發 pipeline,最後變成了一篇沒有人敢修改的散文。

但它到底是怎麼長胖的?

我回頭翻 Git 紀錄,才發現它不是慢慢長大的。最早的 coordinator 文件只有 221 行,兩天後已經變成 419 行。

這 198 行不是預先設計好的流程,而是事故留下來的痕跡。

每次出事,我都會補一條看起來很合理的規則。問題確實解掉了,文件也確實愈來愈難維護。

第一次:做了 mock,卻說功能完成了

使用這套流程時,為了更容易理解 Spec,我要求 agent 把規格轉成 HTML 頁面,發布到專用網站,方便團隊審核。

其中一次,agent 完成了規格文件,也做出一份放在 public/mock 的靜態頁面。

接著,它回報功能已經實作完成。

問題是,真正負責執行功能的程式碼(runtime code)根本沒有改。沒有 route handler、沒有 domain object,也沒有真正可以操作的功能。QA 測試的只是設計稿,commit message 寫的內容也和實際 diff 對不起來。

於是我補了一整組規則:

  • coordinator 不能自己假裝完成 engineer 的工作,必須另外派出 engineer agent。
  • diff 裡至少要有 src/tests/、migration 或 script 的變更。
  • 只有 OpenSpec scaffold 或 mock 頁面,不算完成。
  • QA 必須測試實際執行中的應用程式,不能測 public/mock
  • commit message 必須和實際 diff 相符。
  • 進入 AI Review 與 Human Review 前,都要重跑一次 implementation gate。

這次修正增加了 95 行,刪掉 2 行。

一個「不要把 mock 當成實作」的觀念,就這樣散落在 dispatch、implementation gate、QA、final gate 和 guardrail 五個地方。

當下我覺得這樣比較保險。現在回頭看,這已經是第一個警訊:同一個規則開始出現第二份、第三份副本。

第二次:一張卡長出兩個 branch、兩個 PR

原本的 planning 階段已經替卡片建立 branch 和 draft PR,但 implementation worker 沒有接著使用,反而又開了一組新的 branch 和 PR。

事情還不只這樣。

它的新 branch 是從 local main 切出去的。當時另一條並行中的 pipeline 已經把別張卡片的 mock commit 留在 local main,那些不相干的檔案就一起被帶進新的 PR。

最後,一張卡有兩個 branch、兩個 PR,還混進了另一張卡的檔案。

這次我又補上:

  • 一張卡從頭到尾只能有一個 branch 和一個 PR。
  • implementation 必須沿用 planning 留下的 branch 與 draft PR。
  • 建 branch 前一定要 fetch,並以 origin/main 為基準,不能相信 local main
  • diff 裡如果出現其他卡片的 mock 檔案,立即停止。
  • push 後把原本的 draft PR 標成 ready,不能再開一個新的。

這次修改增加 41 行、刪除 13 行,文件淨增加 28 行。

真正缺少的其實只有兩個不變量(invariant):

一張卡只有一個 branch 和一個 PR。

新工作只能從乾淨的基準開始。

但當流程只能用散文表達時,我只好把這兩件事分別塞進工作步驟、gate、指令範例和 guardrail。

第三次:worktree 還在,唯一的紀錄卻不見了

後來,問題從流程文件進到資源清理。

teardown 會執行 git worktree remove,然後從流程帳本(ledger)刪除這張卡的紀錄。但當移除 worktree 失敗時,程式沒有處理失敗結果,仍然刪除了流程帳本裡的紀錄。

目錄還留在硬碟上,系統卻已經忘記它的位置。

當時在這台機器上實際找到 7 個 worktree,流程帳本裡卻只剩 2 筆紀錄。每個 worktree 裡的 node_modules 大約占 1 GB。

為了處理這件事,我補上:

  • worktree 移除失敗時,保留流程帳本裡的紀錄。
  • teardown 必須回報實際錯誤,不能假設清理成功。
  • 修正原因後可以安全地重新執行 teardown。
  • 清查程序(sweep)要找出仍存在於硬碟、卻沒有登記在流程帳本裡的孤兒 worktree(orphan worktree)。
  • 孤兒 worktree 只能列出來,不能自動刪除,因為裡面可能還有未提交的修改。
  • 文件也要更正 teardown 真正發生的階段。

這次修改跨了文件與程式,增加 95 行、刪除 9 行。

一句「清理失敗時要重試」已經處理不了這個問題。它牽涉資源生命週期、錯誤回復、資料所有權,以及哪些東西可以安全刪除。

但我的修法仍然一樣:把這次學到的事繼續寫進流程。

第四次:一個單字,變成一張 Backlog 卡

另一個事故發生在 code review。

當時的規則只寫了兩種處理方式:code review 提出的問題(finding)合理就修掉,不合理就回覆說明。可是,如果問題合理,卻不值得在這個 PR 處理呢?

規則沒有答案,worker 只好自己決定。

它為了修改 UI 上的一個單字,建立了一張新的 Trello Backlog 卡。13 分鐘後,重新檢查才發現這個問題其實應該直接在原 PR 修掉,那張卡也隨即被封存。

於是我又補了第三條路:

  • 可以延後處理的問題,留在原本的 PR 討論串。
  • 在 review gate comment 裡記一行原因。
  • 不得為每個小問題新建 Trello 卡。
  • 只有問題真的會活得比這個 PR 更久,或人明確要求追蹤時,才能建立後續卡片。
  • build、review 與 reference 文件都要寫清楚同一件事。

這次增加 33 行、刪除 4 行。

為了一個存在 13 分鐘的 Backlog 卡,永久規則又多了 29 行。

兩天,221 行變成 419 行

只看最早期 coordinator 文件的 Git 歷史,它的成長是這樣:

06/22  初版 coordinator                 221 行
06/23  整併 QA、review、PR             247 行
06/24  補 implementation gate          340 行
06/24  加入 CardSize gate              391 行
06/24  修正 branch/PR 與 clean base    419 行

兩天內,文件幾乎翻倍。

後來我做了整體重構,檔案結構已經不同,不能直接接在同一條曲線上比較。不過,重構後的第一個版本有 23 個檔案,共 4,783 行,其中 Markdown 占 1,523 行。

隔天修完 worktree 和 review finding 兩個事故後,總行數來到 4,898 行,Markdown 則增加到 1,591 行。

檔案拆開了,規則仍然繼續增加。

每一條規則都對,放在一起卻不一定對

這四次修改都有充分的理由。

mock 不能假裝是正式功能;一張卡不該有兩個 PR;worktree 還沒移除,就不能刪掉唯一的紀錄;review 提出的問題也不該無限制地製造 Backlog 卡。

真正的問題是,我每次都把事故留下來,卻沒有把事故背後的不變量留下來。

於是,同一個觀念會同時出現在:

  • coordinator 的工作步驟;
  • worker prompt;
  • shell command;
  • QA gate;
  • Human Review 前的 final gate;
  • 文件最後的 guardrail。

下一次修改時,agent 必須記得一起更新所有副本。只漏一個地方,文件說的、程式做的和 agent 理解的就會開始漂移。

散文沒有 compiler,也不會告訴我同一條規則已經被寫了五次。

我原本以為

流程寫得愈詳細,agent 就愈不容易犯錯。

實際上

兩天,221 行變成 419 行。我一開始並非少寫了 198 行;只是每次出事時,我都只能再補一段文字。

每次事故真正該留下的,是一個可以被驗證的不變量。


上一篇
Day 1|我用 skill 編排了一條 AI 開發 pipeline,然後它失控了
下一篇
Day03 沒有測試的 AI 重構:十二輪 review 教我的六種失敗形態
系列文
你的 Agent 流程不該是一篇散文3
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言